import React, { useState } from 'react';
import Web3 from 'web3';
import styles from './components.module.less';
import { Button, Checkbox, Input, Typography } from 'antd';
import { observer } from 'mobx-react-lite';

interface ContractInteractionProps {
  web3: Web3 | null;
  account: string;
  isConnected: boolean;
  onResult: (result: string) => void;
}

const ContractInteraction = observer(({ web3, account, isConnected, onResult }: ContractInteractionProps) => {
  const [contractAddress, setContractAddress] = useState<string>('');
  const [contractABI, setContractABI] = useState<string>('[]');
  const [contract, setContract] = useState<any>(null);
  const [functionName, setFunctionName] = useState<string>('');
  const [functionParams, setFunctionParams] = useState<string>('[]');
  const [isWriteFunction, setIsWriteFunction] = useState<boolean>(false);
  const [isLoading, setIsLoading] = useState<boolean>(false);
  const [addressError, setAddressError] = useState<string>('');
  const [abiError, setAbiError] = useState<string>('');
  const [paramsError, setParamsError] = useState<string>('');

  // 验证以太坊地址
  const validateAddress = (address: string) => {
    if (!address) {
      setAddressError('请输入合约地址');
      return false;
    }
    if (!web3?.utils.isAddress(address)) {
      setAddressError('请输入有效的以太坊地址');
      return false;
    }
    setAddressError('');
    return true;
  };

  // 验证ABI格式
  const validateABI = (abi: string) => {
    if (!abi) {
      setAbiError('请输入合约ABI');
      return false;
    }
    try {
      const parsedABI = JSON.parse(abi);
      if (!Array.isArray(parsedABI)) {
        setAbiError('ABI必须是JSON数组格式');
        return false;
      }
      setAbiError('');
      return true;
    } catch (error) {
      setAbiError('ABI格式错误，请输入有效的JSON');
      return false;
    }
  };

  // 验证参数格式
  const validateParams = (params: string) => {
    if (!params) {
      setParamsError('');
      return true;
    }
    try {
      const parsedParams = JSON.parse(params);
      if (!Array.isArray(parsedParams)) {
        setParamsError('参数必须是JSON数组格式');
        return false;
      }
      setParamsError('');
      return true;
    } catch (error) {
      setParamsError('参数格式错误，请输入有效的JSON数组');
      return false;
    }
  };

  // 创建合约实例
  const createContract = async () => {
    if (!validateAddress(contractAddress) || !validateABI(contractABI)) {
      return;
    }

    if (!web3) {
      onResult('Web3实例未初始化，请刷新页面重试');
      return;
    }

    setIsLoading(true);
    try {
      const abi = JSON.parse(contractABI);
      const contractInstance = new web3.eth.Contract(abi, contractAddress);
      setContract(contractInstance);
      onResult('合约实例创建成功');
      console.log('合约实例创建成功');
    } catch (error) {
      console.error('创建合约实例失败:', error);
      onResult('创建合约实例失败: ' + (error as Error).message);
    } finally {
      setIsLoading(false);
    }
  };

  // 复制到剪贴板功能
  const copyToClipboard = (text: string, label: string) => {
    navigator.clipboard.writeText(text).then(() => {
      onResult(`${label}已复制到剪贴板`);
    }).catch(err => {
      console.error('复制失败:', err);
    });
  };

  // 读取合约数据
  const readContractData = async () => {
    if (!contract || !isConnected || !functionName) {
      onResult('请先创建合约实例并输入函数名');
      return;
    }

    if (!validateParams(functionParams)) {
      return;
    }

    setIsLoading(true);
    try {
      onResult('正在读取合约数据...');
      
      let params = [];
      if (functionParams) {
        params = JSON.parse(functionParams);
      }

      const result = await contract.methods[functionName](...params).call();
      const formattedResult = JSON.stringify(result, null, 2);
      onResult('读取合约数据成功: \n' + formattedResult);
      console.log('读取合约数据成功:', result);
    } catch (error) {
      console.error('读取合约数据失败:', error);
      onResult('读取合约数据失败: ' + (error as Error).message);
    } finally {
      setIsLoading(false);
    }
  };

  // 写入合约数据
  const writeToContract = async () => {
    if (!web3 || !contract || !isConnected || !functionName || !account) {
      onResult('请先创建合约实例、输入函数名并确保已连接账户');
      return;
    }

    if (!validateParams(functionParams)) {
      return;
    }

    setIsLoading(true);
    try {
      onResult('正在调用合约函数...');
      
      let params = [];
      if (functionParams) {
        params = JSON.parse(functionParams);
      }

      const gasPrice = await web3.eth.getGasPrice();
      const gasEstimate = await contract.methods[functionName](...params).estimateGas({ from: account });
      
      // 调用合约写函数并发送交易
      const txHash = await contract.methods[functionName](...params).send({
        from: account,
        gas: gasEstimate,
        gasPrice: gasPrice
      });
      
      onResult('调用合约函数成功，交易哈希: ' + txHash.transactionHash);
      console.log('调用合约函数成功:', txHash);
    } catch (error) {
      console.error('调用合约函数失败:', error);
      if ((error as any).code === 4001) {
        onResult('操作被取消: 您拒绝了MetaMask的交易确认请求');
      } else {
        onResult('调用合约函数失败: ' + (error as Error).message);
      }
    } finally {
      setIsLoading(false);
    }
  };

  const isUsingPublicNode = account === '使用公共节点连接';

  return (
    <div className={styles.contractInteraction}>
      <Typography.Title level={4}>智能合约交互</Typography.Title>
      
      <div className={styles.inputGroup}>
        <label>合约地址:</label>
        <div className={styles.inputWithButton}>
          <Input
            value={contractAddress}
            onChange={(e) => {
              setContractAddress(e.target.value);
              if (addressError) validateAddress(e.target.value);
            }}
            onBlur={() => validateAddress(contractAddress)}
            placeholder="0x..."
            className={addressError ? styles.inputError : ''}
          />
          {contractAddress && (
            <button 
              className={styles.copyButton}
              onClick={() => copyToClipboard(contractAddress, '合约地址')}
              title="复制地址"
            >
              📋
            </button>
          )}
        </div>
        {addressError && <div className={styles.errorMessage}>{addressError}</div>}
      </div>
      
      <div className={styles.inputGroup}>
        <label>合约ABI:</label>
        <div className={styles.textareaWithButton}>
          <Input.TextArea
            value={contractABI}
            onChange={(e) => {
              setContractABI(e.target.value);
              if (abiError) validateABI(e.target.value);
            }}
            onBlur={() => validateABI(contractABI)}
            placeholder="输入合约ABI JSON"
            rows={6}
            className={abiError ? styles.inputError : ''}
          />
          {contractABI && (
            <button 
              className={styles.copyButton}
              onClick={() => copyToClipboard(contractABI, '合约ABI')}
              title="复制ABI"
            >
              📋
            </button>
          )}
        </div>
        {abiError && <div className={styles.errorMessage}>{abiError}</div>}
      </div>
      
      <Button
        type="primary"
        onClick={createContract}
        className={styles.actionButton}
        disabled={!web3 || !contractAddress || !contractABI || !!addressError || !!abiError || isLoading}
      >
        {isLoading ? (
          <span className={styles.buttonWithLoader}>
            <span className={styles.loading}></span>
            创建中...
          </span>
        ) : (
          '创建合约实例'
        )}
      </Button>
      
      {contract && (
        <div className={styles.contractFunctionSection}>
          <div className={styles.sectionHeader}>
            <h4>合约函数调用</h4>
            <span className={styles.contractAddressDisplay}>
              合约地址: {contractAddress}
            </span>
          </div>
          
          <div className={styles.inputGroup}>
            <label>函数名:</label>
          <Input
            value={functionName}
            onChange={(e) => setFunctionName(e.target.value)}
            placeholder="如: balanceOf"
          />
          </div>
          
          <div className={styles.inputGroup}>
            <label>函数参数 (JSON数组):</label>
            <Input.TextArea
              value={functionParams}
              onChange={(e) => {
                setFunctionParams(e.target.value);
                if (paramsError) validateParams(e.target.value);
              }}
              onBlur={() => validateParams(functionParams)}
              placeholder='如: ["0x1234..."]'
              rows={2}
              className={paramsError ? styles.inputError : ''}
            />
            {paramsError && <div className={styles.errorMessage}>{paramsError}</div>}
          </div>
          
          <div className={styles.checkboxGroup}>
            <Checkbox
              id="isWriteFunction"
              checked={isWriteFunction}
              onChange={(e) => setIsWriteFunction(e.target.checked)}
              disabled={isUsingPublicNode}
            >这是一个写函数（需要发送交易）</Checkbox>
          </div>
          
          <div className={styles.buttonGroup}>
            {isWriteFunction ? (
              <Button
                type="primary"
                onClick={writeToContract}
                className={styles.actionButton}
                disabled={!isConnected || isUsingPublicNode || !functionName || isLoading || !!paramsError}
              >
                {isLoading ? (
                  <span className={styles.buttonWithLoader}>
                    <span className={styles.loading}></span>
                    发送交易中...
                  </span>
                ) : (
                  '调用写函数'
                )}
              </Button>
            ) : (
              <Button
                onClick={readContractData}
                className={styles.actionButton}
                disabled={!isConnected || !functionName || isLoading || !!paramsError}
              >
                {isLoading ? (
                  <span className={styles.buttonWithLoader}>
                    <span className={styles.loading}></span>
                    读取中...
                  </span>
                ) : (
                  '调用读函数'
                )}
              </Button>
            )}
          </div>
        </div>
      )}
      
      {isUsingPublicNode && (
        <div className={styles.warning}>
          <strong>注意:</strong> 您当前使用的是公共节点，只能进行只读操作。请连接MetaMask钱包以执行写操作。
        </div>
      )}
    </div>
  );
});

export default ContractInteraction;
